#include "stdafx.h"
#include "torrent/Tracker.hpp"

#include "bencode/bencode.h"
#include "torrent/utility.hpp"
#include "torrent/Client.hpp"

#if defined(_WIN32) && defined(_DEBUG)
#define new MYDEBUG_NEW
#endif

namespace torrent {

std::string TrackerRequest::param(const Client& c, const std::string& infoHash,
								  const std::string& event,
								  boost::uint64_t left, boost::uint64_t downloaded, boost::uint64_t uploaded )
{
	//std::string reqPath = "/announce?info_hash=HA%e4%7f%a1%b6%40%ef%c1t%9e%f2%ee%84%11%da%baT%90I"
	//	"&peer_id=-UT2210-%2ab%f2%8f%7d%de%89%93w%ad%2b%97&port=64518&uploaded=0"
	//	"&downloaded=0&left=1971905296&corrupt=0&key=4AB3048F&event=started"
	//	"&numwant=200&compact=1&no_peer_id=1"
	//	"&ipv6=2001%3a0%3a4137%3a9e76%3ac4d%3a793%3a883b%3aca36";

	std::ostringstream oss;

	// meta info
	oss << "info_hash=";
	oss << utility::urlencode(infoHash);

	// client setting value
	oss << "&peer_id=";
	oss << utility::urlencode(c._peerID);
	oss << "&port=";
	oss << c._port;		
	oss << "&numwant=";
	oss << c._numwant;
	oss << "&compact=";
	oss << c._compact;
	oss << "&no_peer_id=";
	oss << c._noPeerID;
	oss << "&key=";
	oss << c._key;

	// for this torrent
	oss << "&uploaded=";
	oss << uploaded;
	oss << "&downloaded=";
	oss << downloaded;
	oss << "&left=";
	oss << left;

	// TODO : num of broken pieces * piece length ( in byte) + last peice length ( when broken )
	oss << "&currupt=";
	oss << 0;

	// state for torrent	
	oss << "&event=";
	oss << event;

	return oss.str();
}

TrackerResponse::TrackerResponse(const std::string& host
	, const std::string& port
	, const std::string& requestPath
	, const std::string& httpContent)
: _host(host), _port(port), _requestPath(requestPath)
, _httpContent(httpContent)
, _node(be_decoden(_httpContent.c_str(), _httpContent.length()))
{
	if (!_node.get())
		return;

	if (be_node* peerNode = bencode_helper::get_node_from_key(_node.get(), "peers"))
	{
		boost::uint64_t len = be_str_len(peerNode);
		const char* p = peerNode->val.s;

		for(size_t i =0;i<static_cast<size_t>(len);)
		{
			unsigned int ip = 0;
			unsigned short port = 0;
			memcpy(&ip,p+i,4);i+=4;
			memcpy(&port,p+i,2);i+=2;

			_peers.push_back(std::make_pair(ntohl(ip), ntohs(port)));
		}
	}
}

TrackerResponse::TrackerResponse(const std::string& host
				, const std::string& port
				, const std::string& requestPath)
: _host(host), _port(port), _requestPath(requestPath)
, _node(NULL)
{
}

std::string TrackerResponse::getFailureReason()
{
	return _node.get() ? bencode_helper::get_str(_node.get(), "failure reason") : "response is null";
}

}
